package com.aijk.commons.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 生成EOP的API配置参数工具类
 * Created by ChenDeWei on 2016/5/25.
 */
public class EopGeneraterUtils {

    private static final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();

    private static final Map<String, String> map = new HashMap<>();


    private static void generateMethod(Class clazz, Method method) {

        //System.out.println( JSON.toJSONString(clazz.getInterfaces()));

        String api = clazz.getTypeName() + "." + method.getName();
        System.out.println("-----------------------------begin-----------------------------");

        List<JSONObject> list = new ArrayList<>();
        Class<?>[] props = method.getParameterTypes();
        String[] paramNames = parameterNameDiscoverer.getParameterNames(method);
        for (int i = 0; i < props.length; i++) {
            Class<?> prop = props[i];
            JSONObject param = new JSONObject();
            param.put("type", prop.getName());
            param.put("name", paramNames[i].toLowerCase());
            if (prop.getName().equalsIgnoreCase("com.lifesea.base.entity.PagingRequest")) {
                list.add(param);
                continue;
            }

            //param.put("name", paramNames[i]);
            if (prop.getName().startsWith("java.")
                    || prop.getName().equalsIgnoreCase("char")
                    || prop.getName().equalsIgnoreCase("short")
                    || prop.getName().equalsIgnoreCase("int")
                    || prop.getName().equalsIgnoreCase("long")
                    || prop.getName().equalsIgnoreCase("double")
                    || prop.getName().equalsIgnoreCase("float")
                    || prop.getName().equalsIgnoreCase("byte")) {
                param.put("dubboName", paramNames[i].toLowerCase());
                list.add(param);
                continue;
            }
            JSONArray jsonArray = new JSONArray();
            Field[] fields = prop.getDeclaredFields();

            for (Field field : fields) {
                if (field.getName().equalsIgnoreCase("serialVersionUID")) {
                    continue;
                }
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("dubboName", field.getName());
                jsonObject.put("type", field.getType());

                JSONField anno = field.getAnnotation(JSONField.class);
                if (anno != null && StringUtils.isNotEmpty(anno.format())) {
                    jsonObject.put("format", anno.format());
                }

                jsonArray.add(jsonObject);
            }
            if (jsonArray.size() > 0) {
                param.put("props", jsonArray);
            }

            list.add(param);
        }
        System.out.println(String.format("api config paraams api=[%s] class=[%s] method=[%s]", api.toLowerCase(), clazz.getName(), method.getName()));
        System.out.println(JSON.toJSONString(list));
        System.out.println("-----------------------------end-----------------------------");
        System.out.println("");
    }

    public static void generate(Class clazz) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            generateMethod(clazz, method);
        }
    }

    public static void generate(Class clazz, String methodName) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isBridge()) {
                continue;
            }
            if (method.getName().equalsIgnoreCase(methodName)) {
                generateMethod(clazz, method);
            }
        }
    }
}
